<ng-template #errorTip let-control>
    <ng-container *ngIf="control.hasError('required')">必填项</ng-container>
    <ng-container *ngIf="control.hasError('pattern')">格式不对</ng-container>
    <ng-container *ngIf="control.hasError('min')">太小了</ng-container>
    <ng-container *ngIf="control.hasError('max')">太大了</ng-container>
    <ng-container *ngIf="control.hasError('minlength')">太短了</ng-container>
    <ng-container *ngIf="control.hasError('maxlength')">太长了</ng-container>
</ng-template>


<!-- 表单模板 -->
<ng-template #controlTpl let-field="field" let-control="control">
    @switch (field.type) {
        @case ('text') {
            <!--文本-->
            <input nz-input [formControl]="control"
                   [minlength]="field.min || 0"
                   [maxlength]="field.max || 255"
                   [placeholder]="field.placeholder || ''"
                   [nzAutocomplete]="auto"/>
            <nz-autocomplete [nzDataSource]="field.auto" #auto></nz-autocomplete>
        }
        @case ('password') {
            <!--密码-->
            <input nz-input type="password" [formControl]="control"
                   [minlength]="field.min || 0"
                   [maxlength]="field.max || 255"
                   [placeholder]="field.placeholder || ''"/>
        }
        @case ('number') {
            <!--数值-->
            <nz-input-number [formControl]="control"
                             [nzMin]="field.min===undefined ? -Infinity : field.min"
                             [nzMax]="field.max===undefined ? Infinity : field.max"
                             [nzStep]="field.step || 1"
                             [nzPlaceHolder]="field.placeholder || ''"></nz-input-number>
        }
        @case ('slider') {
            <!--滑块-->
            <nz-slider [formControl]="control"
                       [nzMin]="field.min || 0"
                       [nzMax]="field.max || 100"
                       [nzStep]="field.step"></nz-slider>
        }
        @case ('radio') {
            <!--单选 有import Bug，先不支持-->
            <nz-radio-group [formControl]="control" nzButtonStyle="solid">
                <label nz-radio-button *ngFor="let o of field.options"
                       [nzValue]="o.value"
                       [nzDisabled]="o.disabled">{{ o.label }}</label>
            </nz-radio-group>
        }
        @case ('select') {
            <!--选项-->
            <nz-select [formControl]="control"
                       [nzOptions]="field.options || empty"
                       [nzPlaceHolder]="field.placeholder || ''"></nz-select>
        }
        @case ('tags') {
            <!--标签-->
            <nz-select nzMode="tags" [formControl]="control"
                       [nzTokenSeparators]="[',','，', ' ', ';']"
                       [nzOptions]="field.options || empty"
                       [nzPlaceHolder]="field.placeholder || '输入 逗号，分号，空格 分隔'"></nz-select>
        }
        @case ('tree') {
            <!--树选择-->
            <nz-tree-select nzShowSearch nzCheckable [formControl]="control"
                            [nzNodes]="field.tree || empty"
                            [nzMultiple]="field.multiple"
                            (nzTreeCheckBoxChange)="field.change?.($event)"
                            [nzPlaceHolder]="field.placeholder || ''"></nz-tree-select>
        }
        @case ('color') {
            <!--颜色-->
            <nz-color-picker nzShowText [formControl]="control" [nzAllowClear]="field.clear"></nz-color-picker>
        }
        @case ('switch') {
            <!--开关-->
            <nz-switch [formControl]="control"></nz-switch>
        }
        @case ('checkbox') {
            <!--开关-->
            <label nz-checkbox [formControl]="control"></label>
        }
        @case ('textarea') {
            <!--多行文本-->
            <nz-textarea-count [nzMaxCharacterCount]="field.max || 255">
                <textarea rows="4" nz-input [formControl]="control"></textarea>
            </nz-textarea-count>
        }
        @case ('slider') {
            <!--进度条-->
            <nz-slider [formControl]="control"
                       [nzMax]="field.max" [nzMin]="field.min" [nzStep]="field.step"></nz-slider>
        }
        @case ('rate') {
            <!--评分-->
            <nz-rate [formControl]="control"></nz-rate>
        }
        @case ('datetime') {
            <!--日期和时间-->
            <nz-date-picker nzShowTime [formControl]="control"
                            [nzPlaceHolder]="field.placeholder || ''"></nz-date-picker>
        }
        @case ('date') {
            <!--日期-->
            <nz-date-picker [formControl]="control" [nzPlaceHolder]="field.placeholder || ''"></nz-date-picker>
        }
        @case ('time') {
            <!--时间-->
            <nz-time-picker [formControl]="control" [nzPlaceHolder]="field.placeholder || ''"></nz-time-picker>
        }
        @case ('file') {
            <!--文件-->
            <nz-input-group nzSearch [nzAddOnAfter]="suffixButton">
                <input nz-input [formControl]="control"
                       [placeholder]="field.placeholder || ''"/></nz-input-group>
            <ng-template #suffixButton>
                <nz-upload [nzAction]="field.upload" [nzShowUploadList]="false" [nzDisabled]="!!field.disabled"
                           (nzChange)="handleUpload(control, $event)">
                    <button nz-button nzType="primary" [disabled]="!!field.disabled">上传</button>
                </nz-upload>
            </ng-template>
        }
        @case ('images') {
            <!--标签-->
            <nz-select nzMode="tags" [formControl]="control"
                       [nzTokenSeparators]="[',','，', ' ', ';']"
                       [nzOptions]="field.options || empty"
                       [nzPlaceHolder]="field.placeholder || '输入 逗号，分号，空格 分隔'"
            ></nz-select>
            <nz-upload [nzAction]="field.upload" nzMultiple [nzDisabled]="!!field.disabled"
                       (nzChange)="handleUploadImages(control, $event)">
                <button nz-button nzType="primary" [disabled]="!!field.disabled">上传</button>
            </nz-upload>
        }
        @case ('object') {
            <!--对象-->
            <ng-container *ngTemplateOutlet="groupTpl; context: { fields: field.children, group:control }">
            </ng-container>
        }
        @case ('list') {
            <!--列表-->
            <a title="添加" (click)="tableAdd(control, field.children)">
                <i nz-icon nzType="plus"></i>添加
            </a>
            <!--内容-->
            <div cdkDropList (cdkDropListDropped)="tableDrop(control, $event)">
                <div *ngFor="let c of control.controls; let i=index" cdkDrag>
                    <nz-space>
                        <a *nzSpaceItem title="排序" style="cursor:move;" cdkDragHandle>
                            <i nz-icon nzType="drag"></i>排序
                        </a>
                        <a *nzSpaceItem title="复制" (click)="tableCopy(field.children, control, i)">
                            <i nz-icon nzType="copy"></i>复制
                        </a>
                        <a *nzSpaceItem title="删除" (click)="tableRemove(control, i)">
                            <i nz-icon nzType="delete"></i>删除
                        </a>
                    </nz-space>
                    <ng-container *ngTemplateOutlet="groupTpl; context: { fields: field.children, group:c }">
                    </ng-container>
                </div>
            </div>
        }
        @case ('table') {
            <!--表格-->
            <nz-table nzSize="small" nzTemplateMode nzBordered>
                <!--表头-->
                <thead>
                <tr>
                    <th *ngFor="let f of field.children;let j=index">{{ f.label }}</th>
                    <th>
                        <a title="添加" (click)="tableAdd(control, field.children)">
                            <i nz-icon nzType="plus"></i>添加
                        </a>
                    </th>
                </tr>
                </thead>
                <!--内容-->
                <tbody cdkDropList (cdkDropListDropped)="tableDrop(control, $event)">
                <tr *ngFor="let c of control.controls; let i=index" cdkDrag>
                    <td *ngFor="let f of field.children; let j=index">
                        <ng-container *ngTemplateOutlet="controlTpl; context: { field: f, control:c.get(f.key) }">
                        </ng-container>
                    </td>
                    <td class="operators">
                        <nz-space>
                            <a *nzSpaceItem title="排序" style="cursor:move;" cdkDragHandle>
                                <i nz-icon nzType="drag"></i>
                            </a>
                            <a *nzSpaceItem title="复制" (click)="tableCopy(field.children, control, i)">
                                <i nz-icon nzType="copy"></i>
                            </a>
                            <a *nzSpaceItem title="删除" (click)="tableRemove(control, i)">
                                <i nz-icon nzType="delete"></i>
                            </a>
                        </nz-space>
                    </td>
                </tr>
                </tbody>
            </nz-table>
        }
        @case ('template') {
            <ng-container *ngTemplateOutlet="field.template; context: { field: field, control:control }">
            </ng-container>
        }
        @default {
            <!--默认 用文本-->
            <span>不支持的控件类型：{{ field.type }}</span>
        }
    }
    {{ field.tips }}
</ng-template>


<!-- 数组模板 -->
<ng-template #arrayTpl let-field="field" let-array="array">
    <a title="添加" (click)="arrayAdd(array, field)">
        <i nz-icon nzType="plus"></i>添加
    </a>

    <nz-table nzSize="small" nzTemplateMode nzBordered>
        <tbody cdkDropList (cdkDropListDropped)="arrayDrop(array, $event)">
        <tr *ngFor="let c of array.controls; let i=index" cdkDrag>
            <td>
                <ng-container *ngTemplateOutlet="controlTpl; context: { field: field, control: c }">
                </ng-container>
            </td>
            <td class="operators">
                <nz-space>
                    <a *nzSpaceItem title="排序" style="cursor:move;" cdkDragHandle>
                        <i nz-icon nzType="drag"></i>
                    </a>
                    <a *nzSpaceItem title="复制" (click)="arrayCopy(field, array, i)">
                        <i nz-icon nzType="copy"></i>
                    </a>
                    <a *nzSpaceItem title="删除" (click)="arrayRemove(array, i)">
                        <i nz-icon nzType="delete"></i>
                    </a>
                </nz-space>
            </td>
        </tr>
        </tbody>
    </nz-table>
</ng-template>

<!-- 表单组模板 -->
<ng-template #groupTpl let-fields="fields" let-group="group">
    @for (field of fields;track field) {
        @if (!field.hidden) {
            <nz-form-item>
                <nz-form-label *ngIf="field.label" [nzSm]="4" [nzXs]="24" [nzRequired]="field.required" [nzFor]="field.key">
                    {{ field.label }}
                </nz-form-label>
                <nz-form-control [nzSm]="20" [nzXs]="24" [nzErrorTip]="errorTip">
                    @if (field.array) {
                        <ng-container *ngTemplateOutlet="arrayTpl; context: { field: field, array: group.get(field.key)}">
                        </ng-container>
                    } @else {
                        <ng-container *ngTemplateOutlet="controlTpl; context: { field: field, control: group.get(field.key)}">
                        </ng-container>
                    }
                </nz-form-control>
            </nz-form-item>
        }
    }
</ng-template>

<!-- 入口 -->
<ng-container *ngTemplateOutlet="groupTpl; context: { fields: _fields, group: group }">
</ng-container>



